Ext.apply(Ext.util.Observable.prototype, function()
{
	function getMethodEvent( method )
	{
		var e = (this.methodEvents = this.methodEvents || {})[method], returnValue, v, cancel, obj = this;

		if( !e )
		{
			this.methodEvents[method] = e = {};
			e.originalFn = this[method];
			e.methodName = method;
			e.before = [];
			e.after = [];

			var makeCall = function( fn, scope, args )
			{
				if( (v = fn.apply(scope || obj, args)) !== undefined )
				{
					if( typeof v == 'object' )
					{
						if( v.returnValue !== undefined )
						{
							returnValue = v.returnValue;
						}
						else
						{
							returnValue = v;
						}
						cancel = !!v.cancel;
					}
					else if( v === false )
					{
						cancel = true;
					}
					else
					{
						returnValue = v;
					}
				}
			};

			this[method] = function()
			{
				var args = Array.prototype.slice.call(arguments, 0), b;
				returnValue = v = undefined;
				cancel = false;

				for( var i = 0, len = e.before.length; i < len; i++ )
				{
					b = e.before[i];
					makeCall(b.fn, b.scope, args);
					if( cancel )
					{
						return returnValue;
					}
				}

				if( (v = e.originalFn.apply(obj, args)) !== undefined )
				{
					returnValue = v;
				}

				for( var i = 0, len = e.after.length; i < len; i++ )
				{
					b = e.after[i];
					makeCall(b.fn, b.scope, args);
					if( cancel )
					{
						return returnValue;
					}
				}
				return returnValue;
			};
		}
		return e;
	}

	var ret =
	{
		beforeMethod: function( method, fn, scope )
		{
			getMethodEvent.call(this, method).before.push(
			{
				fn: fn,
				scope: scope
			});
		},

		afterMethod: function( method, fn, scope )
		{
			getMethodEvent.call(this, method).after.push(
			{
				fn: fn,
				scope: scope
			});
		},

		removeMethodListener: function( method, fn, scope )
		{
			var e = this.getMethodEvent(method);
			for( var i = 0, len = e.before.length; i < len; i++ )
			{
				if( e.before[i].fn == fn && e.before[i].scope == scope )
				{
					e.before.splice(i, 1);
					return;
				}
			}
			for( var i = 0, len = e.after.length; i < len; i++ )
			{
				if( e.after[i].fn == fn && e.after[i].scope == scope )
				{
					e.after.splice(i, 1);
					return;
				}
			}
		},

		relayEvents: function( o, events )
		{
			var me = this;
			function createHandler( ename )
			{
				return function()
				{
					return me.fireEvent.apply(me,
					[
						ename
					].concat(Array.prototype.slice.call(arguments, 0)));
				};
			}
			for( var i = 0, len = events.length; i < len; i++ )
			{
				var ename = events[i];
				me.events[ename] = me.events[ename] || true;
				o.on(ename, createHandler(ename), me);
			}
		},

		enableBubble: function( events )
		{
			var me = this;
			if( !Ext.isEmpty(events) )
			{
				events = Ext.isArray(events) ? events : Array.prototype.slice.call(arguments, 0);
				for( var i = 0, len = events.length; i < len; i++ )
				{
					var ename = events[i];
					ename = ename.toLowerCase();
					var ce = me.events[ename] || true;
					if( typeof ce == 'boolean' )
					{
						ce = new Ext.util.Event(me, ename);
						me.events[ename] = ce;
					}
					ce.bubble = true;
				}
			}
		}
	};

	return ret;
}());

// 在触发事件时进行拦截
Ext.util.Observable.capture = function( o, fn, scope )
{
	o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
};

Ext.util.Observable.observeClass = function( c, listeners )
{
	if( c )
	{
		if( !c.fireEvent )
		{
			Ext.apply(c, new Ext.util.Observable());
			Ext.util.Observable.capture(c.prototype, c.fireEvent, c);
		}
		if( typeof listeners == 'object' )
		{
			c.on(listeners);
		}
		return c;
	}
};
